<?php
/**
 * Created by PhpStorm.
 * User: yf
 * Date: 2018/10/26
 * Time: 5:39 PM
 */

namespace App\HttpController\Api\VersionOne;

use App\Model\ActivityApplyModel;
use App\Model\ActivityModel;
use App\Model\ActivityRuleModel;
use App\Model\ActivitySignModel;
use App\Model\UserModel;
use App\Model\UserPartakeModel;
use App\Utility\CommonTool;
use EasySwoole\Http\Message\Status;
use EasySwoole\HttpAnnotation\AnnotationTag\Param;
use EasySwoole\HttpAnnotation\AnnotationTag\Method;
use EasySwoole\ORM\DbManager;
use EasySwoole\ORM\Exception\Exception;
use EasySwoole\Pool\Exception\PoolEmpty;
use Throwable;

class Index extends VersionBase
{
    protected $whiteList = ['index', 'rank'];

    /**
     * 获取首页数据
     * @Method(allow={POST,GET})
     * @Param(name="user_id", alias="用户ID", integer="", min="0")
     */
    public function index()
    {
        $userId = $this->input('user_id', 0);
        try {
            $rotationList = $this->getRotationList($userId);
        } catch (Exception $e) {
            $rotationList = [];
        } catch (PoolEmpty $e) {
            $rotationList = [];
        } catch (Throwable $e) {
            $rotationList = [];
        }

        try {
            $joinList = $this->getUserApplying($userId);
        } catch (Exception $e) {
            $joinList = [];
        } catch (PoolEmpty $e) {
            $joinList = [];
        } catch (Throwable $e) {
            $joinList = [];
        }

        try {
            $reCommendList = $this->getRecommendList($userId);
        } catch (Exception $e) {
            $reCommendList = [];
        } catch (PoolEmpty $e) {
            $reCommendList = [];
        } catch (Throwable $e) {
            $reCommendList = [];
        }

        $res['rotation_list'] = $rotationList;
        $res['join_list'] = $joinList;
        $res['recommend_list'] = $reCommendList;
        if ($userId > 0) {
            $res['is_login'] = 1;
        } else {
            $res['is_login'] = 0;
        }

        $this->writeJson(Status::CODE_OK, $res, "success");

        return true;
    }

    /**
     * 获取轮播数据
     * @param int $userId
     * @return array
     * @throws Exception
     * @throws PoolEmpty
     * @throws \Throwable
     */
    private function getRotationList(int $userId = 0)
    {
        $recommendList = DbManager::getInstance()->invoke(function ($client) {
            $activityRuleModel = ActivityRuleModel::invoke($client);
            $activityRuleModel->where('is_recommend', 1);
            $activityRuleModel->order('id', 'desc');
            return $activityRuleModel->all();
        });

        $res = [];

        if (!$recommendList) {
            return $res;
        }

        foreach ($recommendList as $one) {
            $temp = [];
            $info = DbManager::getInstance()->invoke(function ($client) use ($one) {
                $activityModel = ActivityModel::invoke($client);
                $activityModel->where('stype_id', $one->stype_id);
                $activityModel->where('expiration_datetime', date('Y-m-d H:i:s'), '>=');
                return $activityModel->get();
            });

            if ($info) {
                $temp['title'] = CommonTool::getTypeName($one->btype_id, 1) . '(' . CommonTool::getTypeName($one->stype_id, 2) . ')';
                $temp['reason'] = $info->name;
                $temp['reward'] = $info->all_reward;
                $isApply = 0;
                if ($userId > 0) {
                    $userApply = DbManager::getInstance()->invoke(function ($client) use ($userId, $info) {
                        $activityApplyModel = ActivityApplyModel::invoke($client);
                        $activityApplyModel->where('user_id', $userId);
                        $activityApplyModel->where('activity_id', $info->id);
                        return $activityApplyModel->get();
                    });

                    if ($userApply) {
                        $isApply = 1;
                    }
                }

                $temp['is_apply'] = $isApply;
                $temp['activity_id'] = $info->id;
                $temp['color'] = $one->style_num;
                $res[] = $temp;
            }
        }

        return $res;
    }

    /**
     * 获取用户参与数据
     * @param int $userId
     * @return array
     * @throws Exception
     * @throws PoolEmpty
     * @throws \Throwable
     */
    private function getUserApplying(int $userId = 0)
    {
        $today = date('Y-m-d');

        $list = DbManager::getInstance()->invoke(function ($client) {
            $activityModel = ActivityModel::invoke($client);
            $activityModel->where('status', 1);
            $activityModel->where('end_date', date('Y-m-d'), '>=');
            $activityModel->order('start_date', 'ASC');
            return $activityModel->all();
        });

        $res = [];

        if (!$list) {
            return $res;
        }

        foreach ($list as $one) {
            if ($userId > 0) {
                $userApply = DbManager::getInstance()->invoke(function ($client) use ($userId, $one) {
                    return ActivityApplyModel::invoke($client)
                        ->changeTableName($userId)
                        ->where('user_id', $userId)
                        ->where('activity_id', $one->id)
                        ->get();
                });

                if (!$userApply) {
                    continue;
                }

                $todayEndTime = $today . ' ' . $one->end_time; // 今天标准结束时间
                $todayEndTimeStamp = strtotime($todayEndTime); // 获取最后签到时间戳
                $todayStartTime = $today . ' ' . $one->start_time; // 今天标准开始时间
                $todayStartTimeStamp = strtotime($todayStartTime); // 获取最早可以打卡签到时间戳
                $needSignNumber = ((strtotime($today) - strtotime($one->start_date)) / 86400); // 获取应该签到的日期(今天尚未打卡)

                // 如果还没到打卡时间
                $nowTime = time();
                $needSignTrueNumber = 0;
                if ($nowTime < $todayStartTimeStamp) {
                    // 如果还未到打卡时间  则实际需要打卡不需要+1
                    $needSignTrueNumber = $needSignNumber;
                } elseif ($nowTime >= $todayStartTimeStamp && $nowTime <= $todayEndTimeStamp) {
                    // 到了打卡时间,查询该用户是否已经打卡

                    $todayIsSign = DbManager::getInstance()->invoke(function ($client) use ($userId, $one, $todayStartTime, $todayEndTime) {
                        $activitySignModel = ActivitySignModel::invoke($client)
                            ->changeTableName($userId)
                            ->where('user_id', $userId)
                            ->where('activity_id', $one->id)
                            ->where('sign_datetime', [$todayStartTime, $todayEndTime], 'between');
                        return $activitySignModel->get();
                    });

                    if ($todayIsSign) {
                        // 如果已经打卡 需要+1
                        $needSignTrueNumber = $needSignNumber + 1;
                    } else {
                        // 如果未打卡 则不需要+1
                        $needSignTrueNumber = $needSignNumber;
                    }
                } elseif ($nowTime > $todayEndTimeStamp) {
                    // 如果过了打卡时间 则需要+1
                    $needSignTrueNumber = $needSignNumber + 1;
                }

                if ($needSignTrueNumber == $userApply->sign_time || $needSignTrueNumber <= 0) {
                    $temp = [];
                    $temp['title'] = CommonTool::getTypeName($one->btype_id, 1) . '(' . CommonTool::getTypeName($one->stype_id, 2) . ')';
                    $temp['reason'] = $one->name . '期';
                    $temp['start_time'] = substr($one->start_time, 0, -3); //打卡开始小时
                    $temp['end_time'] = substr($one->end_time, 0, -3); //打卡结束小时
                    $temp['reward'] = $one->all_reward;  //总奖金
                    $temp['all_enrollment'] = $one->all_enrollment;  // 参赛人数
                    $temp['activity_id'] = $one->id;
                    if ($todayEndTimeStamp < time()) {
                        $nextSignTime = $todayEndTimeStamp + 86400 - time();
                    } else {
                        $nextSignTime = $todayEndTimeStamp - time();
                    }
                    $temp['next_sign_time'] = $nextSignTime;
                    $res[] = $temp;
                }

            }
        }

        if (count($res) > 0) {
            $lastNames = array_column($res, 'next_sign_time');
            array_multisort($lastNames, SORT_ASC, $res);
        }

        return $res;
    }

    /**
     * 获取推荐数据
     * @param int $userId
     * @return array
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    private function getRecommendList(int $userId = 0)
    {
        $recommendList = DbManager::getInstance()->invoke(function ($client) {
            return ActivityRuleModel::invoke($client)
                ->where('is_recommend', 1)
                ->order('id', 'desc')
                ->all();
        });

        $res = [];

        if (!$recommendList) {
            return $res;
        }

        foreach ($recommendList as $one) {
            $temp = [];

            $info = DbManager::getInstance()->invoke(function ($client) use ($one) {
                return ActivityModel::invoke($client)
                    ->where('stype_id', $one->stype_id)
                    ->where('start_date', date('Y-m-d', time() + 86400))
                    ->get();
            });

            if ($info) {
                $temp['title'] = CommonTool::getTypeName($one->btype_id, 1) . '(' . CommonTool::getTypeName($one->stype_id, 2) . ')';
                $temp['reason'] = $info->name;
                $temp['start_time'] = substr($one->start_time, 0, -3); //打卡开始小时
                $temp['end_time'] = substr($one->end_time, 0, -3); //打卡结束小时
                $temp['reward'] = $one->all_reward;
                $isApply = 0;
                if ($userId > 0) {
                    $userApply = DbManager::getInstance()->invoke(function ($client) use ($userId, $info) {
                        return ActivityApplyModel::invoke($client)
                            ->changeTableName($userId)
                            ->where('user_id', $userId)
                            ->where('activity_id', $info->id)
                            ->get();
                    });

                    if ($userApply) {
                        $isApply = 1;
                    }
                }

                $temp['is_apply'] = $isApply;
                $temp['activity_id'] = $one->id;
                $temp['color'] = $one->style_num;
                $res[] = $temp;
            }
        }

        return $res;
    }

    /**
     * 获取排行榜
     * @Method(allow={POST, GET})
     * @Param(name="pn", alias="分页", required="", integer="", min="1", max="5", notEmpty="不能为空")
     */
    public function rank()
    {
        $pn = $this->input('pn', 1);
        $ps = 20;
        $requestParamData = [
            'pn' => $pn,
            'ps' => $ps,
        ];

        try {
            $res = $this->getRankList($requestParamData);
        } catch (Exception $e) {
            $res = [];
        } catch (PoolEmpty $e) {
            $res = [];
        } catch (Throwable $e) {
            $res = [];
        }

        $this->writeJson(Status::CODE_OK, $res, "success");

        return true;
    }

    /**
     * 获取用户排行榜数据
     * @param array $data
     * @return array
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    private function getRankList(array $data = [])
    {
        $res = [];

        if ($data['pn'] > 5) {
            return $res;
        }

        $rankList = DbManager::getInstance()->invoke(function ($client) use ($data) {
            $limit = ($data['pn'] - 1) * $data['ps'];
            return UserPartakeModel::invoke($client)
                ->field(['user_id', 'prize'])
                ->order('prize', 'desc')
                ->limit($limit, $data['ps'])
                ->all();
        });

        if (!$rankList) {
            return $res;
        }

        foreach ($rankList as $k => $v) {
            $temp = [];

            $userInfo = DbManager::getInstance()->invoke(function ($client) use ($v) {
                return UserModel::invoke($client)
                    ->field(['id', 'nick_name', 'headimg_url'])
                    ->where('id', $v->user_id)
                    ->get();
            });

            if (!$userInfo) {
                continue;
            }

            $temp['nick_name'] = $userInfo->nick_name;
            $temp['headimg_url'] = $userInfo->headimg_url;
            $temp['user_id'] = $v->user_id;
            $temp['money'] = $v->prize;
            $temp['total_sign'] = DbManager::getInstance()->invoke(function ($client) use ($v) {
                return ActivitySignModel::invoke($client)
                    ->changeTableName($v->user_id)
                    ->where('user_id', $v->user_id)
                    ->group('LEFT(`sign_datetime`, 10)')
                    ->count();
            });
            $temp['rank_num'] = $k + (($data['pn'] - 1) * $data['ps']) + 1;
            $res[] = $temp;
        }

        return [
            'total' => 5,
            'per_page' => intval($data['ps']),
            'current_page' => intval($data['pn']),
            'last_page' => 5,
            'is_last_page' => intval(($data['pn'] == 5 ? 1 : 0)),
            'data' => $res,
        ];
    }
}